package me.yangbajing.web
package snippet

import scala.xml.{Elem, Unparsed, NodeSeq}
import scala.collection.mutable

import net.liftweb.common.{Failure, Loggable, Full}
import net.liftweb.http.{S, SHtml, DispatchSnippet}
import net.liftweb.util.Helpers._
import net.liftweb.http.js.{JE, JsCmd, JsCmds}
import net.liftweb.util.ClearNodes

import me.yangbajing.model.MUser
import me.yangbajing.helper.MeHelpers

object SessionSnippet extends DispatchSnippet with Loggable {

  def dispatch = {
    case "head" => head
    case "html5Shiv" => html5Shiv
    case "respond" => respond
    case "navbarTop" => navbarTop
    case "oldIE" => oldIE
    case "userInfo" => userInfo
    case "breadcrumb" => breadcrumb
    case "signIn" => signIn
    case "signUp" => signUp
  }

  def head(nodeSeq: NodeSeq): NodeSeq = {
    val config = MeHelpers.config
    config.html_meta match {
      case Nil =>
        nodeSeq

      case vs =>
        vs.map(v => s"name=${v.name} [content]" #> v.content).reduceLeft(_ & _) apply nodeSeq
    }
  }

  def html5Shiv(nodeSeq: NodeSeq): NodeSeq =
    Unparsed( """<!--[if lt IE 9]><script src="/asserts/js/html5shiv.js"></script><![endif]-->""")

  def respond(nodeSeq: NodeSeq): NodeSeq =
    Unparsed( """<!--[if lt IE 9]><script src="/asserts/js/respond/respond.min.js"></script><![endif]-->""")

  def navbarTop(nodeSeq: NodeSeq): NodeSeq = {
    val ajaxLoaderSel =
      "#ajax-loader" #> (
        S.ieVersion match {
          case Full(v) if v < 10 => "span" #> ClearNodes
          case _ => "img" #> ClearNodes
        })

    val mainMenuSel =
      W.theAccount.is match {
        case Full(account) =>
          "#user-account" #> account.user.nickOrId &
            "#me-user-id [value]" #> account.id &
            "#c-not-sign_in" #> ClearNodes

        case _ =>
          "#c-sign_in" #> ClearNodes
      }

    val cssSel =
      ajaxLoaderSel &
        mainMenuSel

    cssSel(nodeSeq)
  }

  def oldIE(nodeSeq: NodeSeq): NodeSeq = {
    val result = for {
      v <- S.ieVersion if v < 9 // 小于IE9
    } yield {
      nodeSeq
    }

    result openOr NodeSeq.Empty
  }

  def userInfo(nodeSeq: NodeSeq): NodeSeq =
    MeHelpers.config.site.account match {
      case Some(account) if MUser.existsById(account) =>
        <div data-lift={"embed?what=/h/user/_info;account=" + account}></div>
      case _ =>
        NodeSeq.Empty
    }

  def breadcrumb(nodeSeq: NodeSeq): NodeSeq = {
    val lis = mutable.ListBuffer[Elem]()

    // TODO

    (".breadcrumb li" #>> lis) apply nodeSeq
  }

  def signIn(nodeSeq: NodeSeq): NodeSeq = {
    var account = ""
    var password = ""
    var remember = false
    val gotoPage = S.param("goto_page")
    val _passwordId = nextFuncName

    def submitFunc(): JsCmd =
      MUser.findOne(account, password) match {
        case Full(user) =>
          W.saveSessionAndCookie(user, remember)
          gotoPage match {
            case Full(uri) =>
              JsCmds.Alert("登陆成功，将跳转到之前访问页面！") &
                JsCmds.RedirectTo(uri)

            case _ =>
              val redirectUri = gotoPage openOr "/"

              JsCmds.Alert("登陆成功！") &
                JsCmds.RedirectTo(redirectUri)
          }

        case Failure(msg, _, _) =>
          $("#" + _passwordId).value("").cmd &
            JE.Call("formControlError", "#sign-in-control-submit", "登陆失败：" + msg).cmd

        case _ =>
          $("#" + _passwordId).value("").cmd &
            JE.Call("formControlError", "#sign-in-control-submit", s"账号：$account 不存在！").cmd
      }

    val cssSel =
      "@account" #> SHtml.text(account, account = _) &
        "@password" #> SHtml.password(password, password = _, "id" -> _passwordId) &
        "@remember" #> SHtml.checkbox(remember, remember = _) &
        "@submit" #> SHtml.hidden(submitFunc)

    cssSel(nodeSeq)
  }

  def signUp(nodeSeq: NodeSeq): NodeSeq = {
    nodeSeq
  }

}
